#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
#include <sw/redis++/redis++.h>

#include "util.hpp"

// 测试 set 和 get
void test1(sw::redis::Redis& redis)
{
    redis.flushall();

    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");

    auto result1 = redis.get("key1");
    if (result1)
    {
        std::cout << result1.value() << std::endl;
    }

    auto result2 = redis.get("key2");
    if (result2)
    {
        std::cout << result2.value() << std::endl;
    }

    auto result3 = redis.get("key3");
    if (result3)
    {
        std::cout << result3.value() << std::endl;
    }

    auto result4 = redis.get("key4");
    if (result4)
    {
        std::cout << result4.value() << std::endl;
    }
}

// 测试 exists
void test2(sw::redis::Redis& redis)
{
    redis.flushall();

    redis.set("key1", "111");
    redis.set("key2", "222");

    auto result1 = redis.exists("key1");
    std::cout << result1 << std::endl;

    auto result2 = redis.exists("key3");
    std::cout << result2 << std::endl;

    auto result3 = redis.exists({"key1", "key2", "key3"});
    std::cout << result3 << std::endl;
}

// 测试 del
void test3(sw::redis::Redis& redis)
{
    redis.flushall();

    redis.set("key1", "111");

    auto result1 = redis.del("key1");    
    std::cout << result1 << std::endl;

    auto result2 = redis.del("key3");
    std::cout << result2 << std::endl;

    redis.set("key1", "111");
    redis.set("key2", "111");
    redis.set("key3", "111");

    auto result3 = redis.del({"key1", "key2", "key3", "key4"});
    std::cout << result3 << std::endl;
}

// 测试 keys
void test4(sw::redis::Redis& redis)
{
    redis.flushall();

    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");
    redis.set("key4", "333");
    redis.set("key5", "333");
    redis.set("key6", "333");

    std::vector<std::string> result1;
    auto it = std::back_insert_iterator(result1);
    redis.keys("*", it);

    printContainer(result1);
}

// 测试 expire 和 ttl
void test5(sw::redis::Redis& redis)
{
    using namespace std::chrono_literals;

    redis.flushall();

    redis.set("key1", "111");
    // 5s => std::chrono::seconds(5) 
    redis.expire("key1", 5s);

    std::this_thread::sleep_for(3s);

    auto result1 = redis.ttl("key1");
    std::cout << result1 << std::endl;
}

// 测试 type
void test6(sw::redis::Redis& redis)
{
    redis.flushall();

    redis.set("key1", "111");
    auto result1 = redis.type("key1");
    std::cout << result1 << std::endl;

    redis.lpush("key2", {"111", "222", "333"});
    auto result2 = redis.type("key2");
    std::cout << result2 << std::endl;

    redis.sadd("key3", {"111", "222", "333"});
    auto result3 = redis.type("key3");
    std::cout << result3 << std::endl;

    redis.zadd("key4", "吕布", 100);
    auto result4 = redis.type("key4");
    std::cout << result4 << std::endl;

    redis.hset("key5", "name", "吕布");
    auto result5 = redis.type("key5");
    std::cout << result5 << std::endl;
}

// 测试 string 类型的相关操作
void test7(sw::redis::Redis& redis)
{
    redis.flushall();

    redis.set("key1", "value1");
    redis.append("key1", "_appended");
    auto result1 = redis.get("key1");
    if (result1)
    {
        std::cout << result1.value() << std::endl; // 输出 "value1_appended"
    }

    redis.set("key2", "100");
    redis.incr("key2");
    auto result2 = redis.get("key2");
    if (result2)
    {
        std::cout << result2.value() << std::endl; // 输出 "101"
    }

    redis.set("key3", "200");
    redis.incrby("key3", 50);
    auto result3 = redis.get("key3");
    if (result3)
    {
        std::cout << result3.value() << std::endl; // 输出 "250"
    }

    redis.set("key4", "300");
    redis.decr("key4");
    auto result4 = redis.get("key4");
    if (result4)
    {
        std::cout << result4.value() << std::endl; // 输出 "299"
    }

    redis.set("key5", "400");
    redis.decrby("key5", 100);
    auto result5 = redis.get("key5");
    if (result5)
    {
        std::cout << result5.value() << std::endl; // 输出 "300"
    }
}

int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");

    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    // test5(redis);
    // test6(redis);
    test7(redis);

    return 0;
}